/**
 Bins.cxx

 \file
 Implementation of class Bins.

 \author Thomas Burton 
 \date 3/2/12
 \copyright 2012 BNL. All rights reserved.
*/

#include "tppmc/Bins.h"
#include <cmath>

#include <algorithm>
#include <iterator>
#include <iostream>
namespace tppmc {
   
   UniformBins::UniformBins()
   : mBins(1, 0., 1.) {
   }


   UniformBins::UniformBins(int n, double min, double max)
   : mBins(n, min, max) {
   }

   int UniformBins::Number() const {
      return mBins.GetNbins();
   }
   
   /**
    Returns (Number() + 1) values defining the interval edges.
    */
   std::vector<double> UniformBins::Edges() const {
      std::vector<double> edges;
      for(int i(1); i <= Number() + 1; ++i) {
         edges.push_back(mBins.GetBinLowEdge(i));
      } // for
      return edges;
   }
   
   /**
    Returns Number() values defining the interval centres.
    */
   std::vector<double> UniformBins::Centres() const {
      std::vector<double> centres;
      for(int i(1); i <= Number(); ++i) {
         centres.push_back(mBins.GetBinCenter(i));
      } // for
      return centres;
   }


   std::vector<std::pair<double, double> > UniformBins::MinMax() const {
      std::vector<double> edges = Edges();
      std::vector<std::pair<double, double> > minmax;
      for(int i(0); i < Number(); ++i) {
         std::pair<double, double> bin(edges.at(i), edges.at(i + 1));
         minmax.push_back(bin);
      } // for
      return minmax;
   }


   Log10Bins::Log10Bins()
   : mBins(1, 1., 10.) {
   }


   Log10Bins::Log10Bins(int n, double min, double max) {
      double width = log10(max / min) / n;
      std::vector<double> values(1, min);
      for(int i(1); i < n; ++i) {
         double x = log10(min) + i * width;
         values.push_back(pow(10., x));
      } // for
      values.push_back(max);
      std::copy(values.begin(), values.end(), std::ostream_iterator<double>(std::cout,"\n"));
      mBins.Set(n, &(values.at(0)));
   }


   int Log10Bins::Number() const {
      return mBins.GetNbins();
   }


   std::vector<double> Log10Bins::Edges() const {
      std::vector<double> edges;
      for(int i(1); i <= Number() + 1; ++i) {
         edges.push_back(mBins.GetBinLowEdge(i));
      } // for
      return edges;
   }
   
   std::vector<double> Log10Bins::Centres() const {
      std::vector<double> centres;
      for(int i(1); i <= Number(); ++i) {
         // ROOT::TAxis already has the logarithmic centre built in,
         // but only in newer version, so for backward compatibility we don't
         // use it. This is basically the implementation there, thought.
         // Log centre = sqrt(low * high)
         double centre = sqrt(mBins.GetBinLowEdge(i) *
                              mBins.GetBinLowEdge(i + 1));
         // If we had a zero or negative bin edge, return normal linear centre
         if(not centre > 0.) {
            centre = 0.5 * (mBins.GetBinLowEdge(i) +
                            mBins.GetBinLowEdge(i + 1));
         } // if
         centres.push_back(centre);
      } // for
      return centres;
   }
   
   
   std::vector<std::pair<double, double> > Log10Bins::MinMax() const {
      std::vector<double> edges = Edges();
      std::vector<std::pair<double, double> > minmax;
      for(int i(0); i < Number(); ++i) {
         std::pair<double, double> bin(edges.at(i), edges.at(i + 1));
         minmax.push_back(bin);
      } // for
      return minmax;
   }

} // namespace tppmc
